package com.bolt.report.engine.calculator;

import com.bolt.common.utils.ArrayUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.report.definition.CalculationType;
import com.bolt.report.engine.BindData;
import com.bolt.report.engine.Calculator;
import com.bolt.report.engine.fill.FillContext;
import com.bolt.report.engine.model.Cell;
import com.bolt.report.engine.model.Expression.CalculatorExpression;
import com.bolt.report.exception.ReportException;

import java.util.HashMap;
import java.util.Map;

public final class CalculatorFactory {

    private static final Map<String, Calculator> calculators;


    static {
        calculators = new HashMap<>();
        calculators.put(CalculationType.SUM.getName(), new SumCalculator());
        calculators.put(CalculationType.MAX.getName(), new MaxCalculator());
        calculators.put(CalculationType.MIN.getName(), new MinCalculator());
        calculators.put(CalculationType.COUNT.getName(), new CountCalculator());
        calculators.put(CalculationType.AVG.getName(), new AvgCalculator());
        calculators.put(CalculationType.FORMATDATE.getName(), new FormatDateCalculator());
        calculators.put(CalculationType.FORMATNUMBER.getName(), new FormatNumberCalculator());
        calculators.put(CalculationType.ROWNUM.getName(), new RowNumCalculator());
        calculators.put(CalculationType.DECODE.getName(), new DecodeCalculator());
        calculators.put(CalculationType.PERCENT.getName(), new PercentCalculator());
        calculators.put(CalculationType.PERCENT.getName(), new ParamCalculator());


    }

    private CalculatorFactory() {
    }

    public static boolean hasCalculator(String name) {
        return calculators.containsKey(name);
    }

    public static Calculator getCalculator(String name) {
        return calculators.get(name);
    }

    public static Object evaluate(FillContext context, BindData data, CalculatorExpression expr, Cell cell) throws ReportException {
        if (expr != null && ArrayUtil.isNotEmpty(expr.getCalculatorName())) {
            String[] names = expr.getCalculatorName();
            Object returnValue = null;
            for (int i = names.length - 1; i >= 0; i--) {
                String name = names[i];
                if (hasCalculator(name)) {
                    Calculator calculator = getCalculator(name);
                    returnValue = calculator.evaluate(context, data, expr, cell);
                    if (i > 0) {
                        data = new BindData(data.getKey(), data.getFieldName(), returnValue,null);
                    }
                }
            }
            return returnValue;
        }
        return StrUtil.EMPTY;
    }
}